﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VentaElectrodomesticos.Negocio;
using VentaElectrodomesticos.Contrato;
using VentaElectrodomesticos.GUI.AbmCliente;
using VentaElectrodomesticos.GUI.Helpers;
using VentaElectrodomesticos.GUI.AbmProducto;
using VentaElectrodomesticos.Datos;
using VentaElectrodomesticos.GUI.Base;

namespace VentaElectrodomesticos.Facturacion
{
    public partial class FormFacturacion : BaseValidaciones
    {
        private static FormFacturacion instance;
        private FacturaNegocio negocio = new FacturaNegocio();
        private Factura factura = new Factura();
        private FormaPagoNegocio formaPagoNegocio = new FormaPagoNegocio();

        private Cliente cliente = new Cliente();
        private FormaPago Efectivo = new FormaPago();
        private Empleado empleado = new Empleado();

        private Pago pago = new Pago();
        private bool sharesPayment = false;

        private Decimal? total = 0;
        private Decimal? monto = 0;
        private Decimal? montoPago = 0;
        private int cuotas = 0;
        private int cuotasApagar = 0;        
        private List<Producto> productos = new List<Producto>();

        public FormFacturacion()
        {
            InitializeComponent();
            this.initialize();
        }

        private void initialize()
        {
            this.dgProducts.AllowUserToAddRows = false;
            this.dgProducts.AllowUserToDeleteRows = false;
            this.dgProducts.EditMode = DataGridViewEditMode.EditProgrammatically;

            Efectivo.Nombre = "Efectivo";

            this.cbProvincia.DataSource = new ProvinciaNegocio().getAll();
            this.cbProvincia.DisplayMember = "Nombre";
            this.cbProvincia.ValueMember = "Id";
            
            this.cbSucursal.DataSource = new SucursalNegocio().getAll();
            this.cbSucursal.DisplayMember = "Direccion";
            this.cbSucursal.ValueMember = "Id";

            this.cbFormaDePago.DataSource = this.formaPagoNegocio.getAll();
            this.cbFormaDePago.DisplayMember = "Nombre";
            this.cbFormaDePago.ValueMember = "Id";


            cbCuotas.Items.Clear();
            cbCuotasAPagar.Items.Clear();
            for (int i = 2; i <= 12; i++)
            {
                cbCuotas.Items.Add(i);
                cbCuotasAPagar.Items.Add(i);
            }

            this.dgProducts.DataSource = this.productos;
            this.tbCliente.ReadOnly = true;

            this.lbCuotasAPagar.Visible = false;
            this.cbCuotasAPagar.Visible = false;
            
            this.tbDescuento.Text = "00";
            this.tbTotal.Text = "";
            this.cliente = new Cliente();
            this.tbCliente.Text = "";
            this.productos = new List<Producto>();
            this.setProductos();

            this.cbSucursal.SelectedValue = Sesion.getInstance().Usuario.__empleado.Sucursal_Id;
            if (Sesion.getInstance().Usuario.__empleado.Provincia_id != null) {
                this.cbProvincia.SelectedValue = Sesion.getInstance().Usuario.__empleado.Provincia_id;
            }
            if (Sesion.getInstance().Usuario.__empleado._Tipo == "Vendedor")
            {
                this.cbProvincia.Enabled = false;
                this.cbSucursal.Enabled = false;
            }
        }

        private void btBuscarCliente_Click(object sender, EventArgs e)
        {
            this.searchCliente();
        }

        private void searchCliente()
        {
            FormAbmCliente formCliente = new FormAbmCliente();            
            DialogResult result = GUIHelper.showFormSearch<FormAbmCliente>(formCliente);
            if (result == DialogResult.OK)
            {
                this.tbCliente.Text = formCliente.Entity.Nombre + " " + formCliente.Entity.Apellido;
                this.cliente = formCliente.Entity;
            }
        }

        private void btAgregarProducto_Click(object sender, EventArgs e)
        {
            this.AddProduct();        
        }

        private void AddProduct()
        {
            if (this.cbSucursal.SelectedItem == null){
                List<String> error = new List<String>();
                error.Add("Debe seleccionar una sucursal para poder agregar un producto");
                this.mostrarErrores(error);
                return;
            }
   
            FormAbmProducto formProducto = new FormAbmProductoStock();
            formProducto.sucursal_id = Convert.ToInt64(cbSucursal.SelectedValue);
            DialogResult result = GUIHelper.showFormSearch<FormAbmProducto>(formProducto);
            if (result == DialogResult.OK)
            {
                Producto producto = formProducto.Entity;
                Producto productoExistente = this.productos.FirstOrDefault(p => p.Id == producto.Id);
                if (productoExistente != null)
                    producto = productoExistente;
                else
                    this.productos.Add(producto);

                FormCantidadProducto frmCantidad = new FormCantidadProducto();
                frmCantidad.StartPosition = FormStartPosition.CenterScreen;
                GUIHelper.showFormSearch<FormCantidadProducto>(frmCantidad);                

                producto.__cantidad += frmCantidad.cantidad;
                producto.__total += producto.__cantidad * producto.Precio.Value;
                
                this.setProductos();
            }
            this.calculateTotal();            
        }

        private void setProductos()
        {
            BindingSource bindingSource = new BindingSource();
            bindingSource.DataSource = this.productos;
            this.dgProducts.DataSource = bindingSource;

            dgProducts.Columns["Categoria_Id"].Visible = false;
            dgProducts.Columns["__cantidad"].HeaderText = "Cantidad";
            dgProducts.Columns["__total"].HeaderText = "Total";
            dgProducts.Columns["descripcion"].Visible = false;
            dgProducts.Columns["__precioMax"].Visible = false;
            dgProducts.Columns["__precioMin"].Visible = false;

            dgProducts.Columns["id"].Visible = true;
            dgProducts.Columns["id"].HeaderText = "Codigo";
        }

        private void btComprar_Click(object sender, EventArgs e)
        {
            this.save();
        }

        private void getValues()
        {
            this.factura.Cliente_Id = this.cliente.Id;
            this.factura.Sucursal_Id = Convert.ToInt32(this.cbSucursal.SelectedValue);
            this.factura.Fecha = DateTime.Now.ToString(Config.regionTimeFormat);
            this.factura.Empleado_Id = Sesion.getInstance().Usuario.empleado_id;
            this.factura.Monto = this.monto;
            this.factura.Descuento = this.getDiscount();
            this.factura.Cuotas = this.cuotas;
            this.factura.Total = this.total;
            this.factura.__productos = this.productos;
            this.factura.__pago = this.pago;
        }

        protected override void doSave()
        {
            this.calculateTotal();
            this.generatePago();
            this.getValues();
            try
            {
                this.negocio.save(this.factura);
                MessageBox.Show("Factura Realizada Correctamente", "Ok", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
            this.initialize();
         }        

        private void cbFormaDePago_SelectedIndexChanged(object sender, EventArgs e)
        {
            selectFormaPago();
        }

        private void selectFormaPago()
        {
            FormaPago formapago = this.cbFormaDePago.SelectedItem as FormaPago;
            this.sharesPayment = formapago != null && formapago.Nombre != Efectivo.Nombre;

            lbCuotas.Visible = cbCuotas.Visible = lbCuotasAPagar.Visible = cbCuotasAPagar.Visible = this.sharesPayment;
            this.calculateTotal();
        }

        private void tbDescuento_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                this.calculateTotal();
        }
                
        private void calculateTotal()
        {
            this.monto = this.negocio.calculateTotal(this.productos);
            if (this.sharesPayment)
            {
                this.cuotas = Convert.ToInt32(this.cbCuotas.SelectedItem);
                this.cuotasApagar = Convert.ToInt32(this.cbCuotasAPagar.SelectedItem);
            }
            else
            {
                this.cuotas = 0;
                this.cuotasApagar = 0;
            }
            this.total = this.negocio.applyDiscount(this.monto, this.getDiscount());
            this.montoPago = this.total;
            if (this.sharesPayment)
            {
                this.montoPago = this.negocio.applyCuotas(this.total, this.cuotas, this.cuotasApagar);
            }
            this.tbTotal.Text = this.montoPago.ToString();
        }

        private void generatePago()
        {
            this.pago.fecha = DateTime.Now.ToString(Config.regionTimeFormat);
            this.pago.sucursal_id = (int)cbSucursal.SelectedValue;
            this.pago.provincia_id = (int)cbProvincia.SelectedValue;
            this.pago.empleado_id = Sesion.getInstance().Usuario.__empleado.Id;

            this.pago.monto = this.montoPago;
            if (!this.sharesPayment)
            {
                this.cuotas = 0;
                this.cuotasApagar = 0;
            }
        }

        private decimal getDiscount()
        {
            try
            {
                return Convert.ToInt32(tbDescuento.Text);
            }
            catch (FormatException)
            {
                return 0;
            }
        }

        private void btEliminarProductos_Click(object sender, EventArgs e)
        {
            this.removeProduct();
        }

        private void removeProduct()
        {
            foreach (DataGridViewRow row in this.dgProducts.SelectedRows)
            {
                this.productos.Remove(row.DataBoundItem as Producto);                
            }
            this.setProductos();
            this.calculateTotal();           
        }

        private void tbDescuento_TextChanged(object sender, EventArgs e)
        {
            if (tbDescuento.Text.Length == 2)
                this.calculateTotal();
        }

        private void cbCuotas_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.cuotas = Convert.ToInt32(cbCuotas.SelectedItem);
            this.cbCuotasAPagar.Items.Clear();
            for (int i = 1; i <= this.cuotas; i++)
                this.cbCuotasAPagar.Items.Add(i);
            this.cbCuotasAPagar.SelectedIndex = 0;
            this.calculateTotal();
        }

        protected override void cumpleValidaciones()
        {   if(this.productos.Count == 0)
                this.Errores.Add("Debe seleccionar algun producto.");
            if (!RegCondition.Condition(tbCliente, RegCondition.RegularExpressions.Alphabet))
                this.Errores.Add("El nombre de cliente no es válido");
            TextBox tempDescuento = new TextBox();
            tempDescuento.Text = tbDescuento.Text;
            if (!RegCondition.Condition(tempDescuento, RegCondition.RegularExpressions.Numeric, 0, 30))
                this.Errores.Add("El descuento debe ser un número entre 0 y 30");
            if (!this.negocio.validarStock(productos, (Sucursal)this.cbSucursal.SelectedItem))
                this.Errores.Add("No hay sotck disponible para los productos seleccionados.");
        }

        private void cbCuotasAPagar_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.calculateTotal();
        }

        internal static FormFacturacion getInstance()
        {
            if (instance == null)
            {
                instance = new FormFacturacion();
            }
            instance.BringToFront();
            
            return instance;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            instance = null;
            base.OnClosing(e);
        }


        private class FormAbmProductoStock : FormAbmProducto
        {


            protected override List<Producto> getObjectList()
            {
                if (this.IsSearchForm)
                {
                    return this.Negocio.getProductosConStock(new Producto(), sucursal_id);
                }
                else
                {
                    return base.getObjectList();
                }
            }

            protected override List<Producto> getFilteredObjectList(Producto filter)
            {
                if (this.IsSearchForm)
                {
                    return this.Negocio.getProductosConStock(filter, sucursal_id);
                }
                else
                {
                    return base.getFilteredObjectList(filter);
                }
            }

        }
    }
}
